//
// Created by GF on 2023/10/27.
//

#include <stdio.h> /* printf(); fopen(); */
#include <string.h> /* strcmp(); */
#include <malloc.h> /* malloc(); */
#include "Array_Function.h"

/* 字符数组 - 通过字符串获得下标索引 (Char Array - Get Index by String) */
int Char_Array_Get_Index_By_String(char Char_Array[32][32], char* String) {

    for(int i = 0; i < 32; i++) {
        /*
         * strcmp() :
         * 如果两个字符串相等，则返回0;
         * 如果第一个字符串小于第二个字符串，则返回一个负数;
         * 如果第一个字符串大于第二个字符串，则返回一个正数.
         */
        if (strcmp(Char_Array[i], String) == 0) return i;
    }
    /* ********************************************** */
    return -1;
}

/* 字符数组 - 判断存在某个字符串 (Char Array - Judge Exists String) */
int Char_Array_Judge_Exists_String(char Char_Array[32][32], char* String) {

    int True_Or_False = 0;
    /* ********************************************** */
    for(int i = 0; i < 32; i++) {
        if (strcmp(Char_Array[i], String) == 0) {True_Or_False = 1; break;}
    }
    /* ********************************************** */
    return True_Or_False;
}

/* 字符指针数组 - 通过字符串获得下标索引 (Char PtrArray - Get Index by String) */
int Char_PtrArray_Get_Index_By_String(char* PArray, char* String) {

    char Copy_Arr[32][32] = {'0'};
    /* ********************************************** */
    /*
     * memcpy() :
     * memcpy(arr2, arr1, sizeof(arr2));
     * 将arr1数组的前sizeof(arr2)字节拷贝进arr2中.
     */
    memcpy(Copy_Arr, PArray, sizeof(Copy_Arr));
    /* ********************************************** */
    int Length = sizeof(Copy_Arr) / sizeof(Copy_Arr[0]);
    /* ********************************************** */
    for(int i = 0; i < Length; i++) {
        if (strcmp(Copy_Arr[i], String) == 0) return i;
    }
    /* ********************************************** */
    return -1;
}

/* 字符指针数组 - 分割字符串到指针数组 (Char PtrArray - Split String to PtrArray) */
char** Char_PtrArray_Split_String_To_PtrArray(char* String, const char* Delimiter) {

    /*
     * C语言函数返回数组的三种方法:
     * 1. 使用"static"关键字声明数组 - 例如: static int arr[5] = {1,2,3,4,5};
     * 2. 使用数组指针 - 例如2维数组声明: char** arr = (char**)malloc(sizeof(char*) * 256);
     * 3. 使用"&"引用参数, 引用外部数组地址直接带出值 - 例如 void func(int (&arr)[5], int len) {};.
     */
    char** Result_Array = (char**)malloc(sizeof(char*) * 256);
    /* ********************************************** */
    for (int i = 0; i < 256; i++) Result_Array[i] = (char*)malloc(sizeof(char) * 64);
    /* ********************************************** */
    char Copy_String[1024];
    /*
     * strtok() :
     * 的第1参数Str必须是字符常量指针，否则无法用strtok。
     * 因为strtok是靠替换分割字符为\0来实现的。
     */
    strcpy(Copy_String, String);
    /* ********************************************** */
    char *Ptr_Str;
    Ptr_Str = strtok(Copy_String, Delimiter); /* 第1次分割字符串 */
    /* ********************************************** */
    int i = 1;
    strcpy(Result_Array[0], Ptr_Str); /* 第1次赋值 */
    while (Ptr_Str != NULL) {
        Ptr_Str = strtok(NULL, Delimiter); /* 第i次分割字符串 */
        /* ****************************************** */
        /*
         * Process finished with exit code -1073741819 (0xC0000005):
         * Similar situation: Comparison between Null and non-pointer ('int' and NULL).
         */
        if (Ptr_Str != NULL) strcpy(Result_Array[i], Ptr_Str); /* 第i次赋值 */
        /* ****************************************** */
        i++;
    }
    /* ********************************************** */
    return Result_Array;
}

/* 二维字符指针数组 - 初始化 (Init) */
char*** Char_TwoDimPtrArray_Init(int RowsNum, int ColsNum) {

    char*** TwoDimPtrArray = (char***)malloc(sizeof(char**) * (RowsNum + 1)); /* 分配行数 */
    /* ********************************************** */
    for (int Row = 0; Row < RowsNum; Row++) {
        TwoDimPtrArray[Row] = (char**) malloc(sizeof(char*) * (ColsNum + 1)); /* 按行分配每行多少列 */
        /* ****************************************** */
        for (int Col = 0; Col < ColsNum; Col++) {
            TwoDimPtrArray[Row][Col] = (char*) malloc(sizeof(char) * 64); /* 按行列分配每个值多少字节 */
        } /* ************** Loop 2 End ************** */
    } /* **************** Loop 1 End **************** */
    /* ********************************************** */
    for (int Row = 0; Row < RowsNum; Row++)
        for (int Col = 0; Col < ColsNum; Col++)
            memset(TwoDimPtrArray[Row][Col], 0, sizeof(char) * 64);
    /* ********************************************** */
    /* 最后1行的下一行指向NULL, 便于计算行数 */
    TwoDimPtrArray[RowsNum] = NULL;
    /* ********************************************** */
    /* 最后1列的下一列指向NULL, 便于计算列数 */
    for (int Row = 0; Row < RowsNum; Row++) TwoDimPtrArray[Row][ColsNum] = NULL;
    /* ********************************************** */
    return TwoDimPtrArray;
}

/* 二维字符指针数组 - 获取行数 (Char TwoDimPtrArray - Get Rows Number) */
long long Char_TwoDimPtrArray_Get_RowsNum(char*** TwoDimPtrArray) {

    /*
     * long long : 本质上还是整型, 只不过是一种超长的整型, 不是所有编译器都使用的.
     * int : 32位整型, 取值范围为 -2^31 ~ (2^31 - 1).
     * long : 在32位系统是32位整型, 取值范围为 -2^31 ~ (2^31 - 1), 在64位系统是64位整型, 取值范围为 -2^63 ~ (2^63 - 1).
     * long long : 是64位的整型, 取值范围为 -2^63 ~ (2^63 - 1).
     */
    long long Counter = 0;
    /* ********************************************** */
    while(*TwoDimPtrArray != NULL) {
        Counter += 1;
        /* ****************************************** */
        TwoDimPtrArray++;
    }
    /* ********************************************** */
    return Counter;
}
